import mox, database, services.AccountsService as AccountsService

class AccountsServiceTests(mox.MoxTestBase):

    def setUp(self):
        mox.MoxTestBase.setUp(self)
        self.session = self.mox.CreateMockAnything()
        self.mox.StubOutWithMock(database, "getSession")
        database.getSession().AndReturn(self.session)

    def test_createAccount(self):
        import TestHelper

        self.session.begin().AndReturn(TestHelper.getTransactionMock(self.mox))

        self.mox.StubOutWithMock(AccountsService, "getAccounts")
        AccountsService.getAccounts("login", id=0).AndReturn(None)

        import services.AuthenticationService as AuthenticationService
        self.mox.StubOutWithMock(AuthenticationService, "getUser")
        user = self.mox.CreateMock(database.User)

        amounts = [self.mox.CreateMock(database.Money)]
        account = self.mox.CreateMock(database.Account)
        account.id = 0
        account.name = "account name"
        account.initialAmounts = amounts

        AuthenticationService.getUser("login").AndReturn(user)
        self.session.add(mox.Func(lambda account: account.user == user and \
                                                  account.id == 0 and \
                                                  account.name == "account name" and \
                                                  account.initialAmounts == amounts))
        self.mox.ReplayAll()
        
        self.assertEqual(AccountsService.saveOrUpdateAccount("login", account), 0)

    def test_updateAccount(self):
        import TestHelper
#        from services.AccountsService import AccountsService

        self.session.begin().AndReturn(TestHelper.getTransactionMock(self.mox))

        amounts = [self.mox.CreateMock(database.Money)]
        account = self.mox.CreateMock(database.Account)
        account.id = 1
        account.name = "account name"
        account.initialAmounts = amounts

        self.mox.StubOutWithMock(AccountsService, "getAccounts")
        AccountsService.getAccounts("login", id=1).AndReturn([account])

        self.mox.ReplayAll()

        self.assertEqual(AccountsService.saveOrUpdateAccount("login", account), 1)

    def test_getAccount(self):
        import TestHelper
        self.session.begin().AndReturn(TestHelper.getTransactionMock(self.mox))

        query = self.mox.CreateMockAnything()
        self.session.query(database.Account).AndReturn(query)
        query.join(database.Account.user).AndReturn(query)

        def _andPredicate(clause):
            return (str(clause.left) == "users.login" and clause.right.value == "login") or \
                   (str(clause.left) == "accounts.name" and clause.right.value == "accountName") or \
                   (str(clause.left) == "accounts.id" and clause.right.value == 1)

        query.filter(mox.Func(lambda v: len([clause for clause in v.clauses if _andPredicate(clause)]) == 3)).AndReturn(query)

        expected = self.mox.CreateMock(database.Account)
        query.all().AndReturn([expected])

        self.mox.ReplayAll()

        actual = AccountsService.getAccounts("login", id=1, accountName="accountName")
        self.assertEqual(expected, actual[0])

    def test_getCurrency(self):
        import TestHelper
        self.session.begin().AndReturn(TestHelper.getTransactionMock(self.mox))

        query = self.mox.CreateMockAnything()
        self.session.query(database.Currency).AndReturn(query)

        query.filter(mox.Func(lambda clause: clause.right.value == "UAH" and str(clause.left) == "currencies.code")).AndReturn(query)
        currency = self.mox.CreateMock(database.Currency)
        query.one().AndReturn(currency)

        self.mox.ReplayAll()

        AccountsService.getCurrency("UAH")


